package com.softserveinc.moviedbapp.manager;

import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;

import com.softserveinc.moviedbapp.application.Settings;
import com.softserveinc.moviedbapp.cache.tables.MovieDetailsTable.MovieDetailsColumns;
import com.softserveinc.moviedbapp.cache.tables.MovieImagesTable.MovieImageColumns;
import com.softserveinc.moviedbapp.cache.tables.MovieTable.MovieColumns;
import com.softserveinc.moviedbapp.connection.GeneralException;
import com.softserveinc.moviedbapp.fragment.IMovieDetailsCallback;
import com.softserveinc.moviedbapp.fragment.IMovieListFragmentCallback;
import com.softserveinc.moviedbapp.model.Movie;
import com.softserveinc.moviedbapp.model.MovieDetails;
import com.softserveinc.moviedbapp.provider.MovieDetailsProvider;
import com.softserveinc.moviedbapp.provider.MovieListProvider;
import com.softserveinc.moviedbapp.provider.MovieListType;
import com.softserveinc.moviedbapp.util.MovieAppConstants;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DataManager {

	public static final int DEFAULT_LIST_SIZE = 10;

	private static final String TAG = DataManager.class.getSimpleName();
	private static final int FIRST_PAGE = 1;

	private Settings settings;
	private boolean isConnected;
	private Map<MovieListType, IMovieListFragmentCallback> movieListFragmentMap;
	private IMovieDetailsCallback movieDetailsFragment;
	private MovieDetails movieInfo;
	private Context context;
	private String lastSearchQuery;

	private List<Movie> moviesByRelease;
	private List<Movie> moviesByRating;
	private List<Movie> moviesByTitle;
	private List<Movie> moviesSearchList;

	private int currentPageTitle = 1;
	private int currentPageRelease = 1;
	private int currentPageRating = 1;

	private BitMapManager bitMapManager;
	private MovieDetailsRetrieverAsync movieDetailsRetrieverAsync;
	private MovieDetailsScreensRetrieverAsync movieDetailsScreensRetrieverAsync;
	private MoviePosterRetrieverAsync moviePosterRetrieverAsync;
	private MovieListRetrieverAsync movieListRetrieverAsync;

	private SearchMovieListAsync searchMovieListAsync;

	public DataManager(final Context ctx, final Settings settings, final BitMapManager bmm) {
		context = ctx;
		this.settings = settings;
		bitMapManager = bmm;
		createMovieListFragmentMap();
	}

	public AsyncTaskWrapper provideMovieList(final MovieListType listType, final String searchQuery) {
		String orderBy = getSortingOrder(listType);

		if (searchQuery == null) {
			/* no search, just show movie list */
			movieListFragmentMap.get(listType).onGettingMovieList();
			if (getMovieList(orderBy) == null) {
				Log.d(TAG, "Going for the movie list, no instance in memory for listType " + listType);
				ListTypeWrapper wrapper = new ListTypeWrapper();
				wrapper.setListType(listType);
				wrapper.setCurrentPage(FIRST_PAGE);
				movieListRetrieverAsync = new MovieListRetrieverAsync();
				movieListRetrieverAsync.execute(wrapper);
				AsyncTaskWrapper asyncTaskWrapper = new AsyncTaskWrapper(movieListRetrieverAsync);
				return asyncTaskWrapper;
			} else {
				Log.d(TAG, "Returning saved instance of movie list from memory for listType " + listType);
				movieListFragmentMap.get(listType).onMovieListRetrieved(getMovieList(orderBy));
				return null;
			}
		} else {
			/* search for a title */
			movieListFragmentMap.get(listType).onGettingMovieList();
			if (lastSearchQuery == null || !lastSearchQuery.equals(searchQuery)) {
				Log.d(TAG, "inside manageMovieList() GOING INTO SEARCH");
				lastSearchQuery = searchQuery;
				searchMovieListAsync = new SearchMovieListAsync();
				searchMovieListAsync.execute(searchQuery);
				AsyncTaskWrapper asyncTaskWrapper = new AsyncTaskWrapper(searchMovieListAsync);
				return asyncTaskWrapper;
			} else {
				Log.d(TAG, "inside manageMovieList() RETURNING SAVED SEARCH INSTANCE");
				movieListFragmentMap.get(listType).onMovieListRetrieved(moviesSearchList);

				return null;
			}
		}
	}

	public AsyncTaskWrapper provideNextPage(final MovieListType listType) {
		Log.d(TAG, "providing the next page for listType " + listType);
		movieListFragmentMap.get(listType).onGettingMovieList();
		ListTypeWrapper wrapper = new ListTypeWrapper();
		wrapper.setListType(listType);
		wrapper.setCurrentPage(getCurrentPage(listType));
		movieListRetrieverAsync = new MovieListRetrieverAsync();
		movieListRetrieverAsync.execute(wrapper);

		AsyncTaskWrapper asyncTaskWrapper = new AsyncTaskWrapper(movieListRetrieverAsync);
		return asyncTaskWrapper;
	}

	public AsyncTaskWrapper provideMoviePosters(final List<Movie> movies, final MovieListType fragmentType) {
		Log.d(TAG, "gonna get movie posters");
		moviePosterRetrieverAsync = new MoviePosterRetrieverAsync();
		ListWrapper listWrapper = new ListWrapper();
		listWrapper.setMovies(movies);
		listWrapper.setFragmentType(fragmentType);
		moviePosterRetrieverAsync.execute(listWrapper);

		AsyncTaskWrapper asyncTaskWrapper = new AsyncTaskWrapper(moviePosterRetrieverAsync);
		return asyncTaskWrapper;
	}

	public void provideMovieDetails(final int movieId) {
		if (movieInfo == null || movieInfo.getMovieId() != movieId) {
			Log.d(TAG, "Going for the movie info, no instance in memory movieId = " + movieId);
			movieDetailsRetrieverAsync = new MovieDetailsRetrieverAsync();
			movieDetailsRetrieverAsync.execute(movieId);
		} else {
			Log.d(TAG, "Returning saved instance of movie info from memory");
			movieDetailsFragment.onGettingMovieInfo();
			movieDetailsFragment.onMovieInfoRetrieved(movieInfo);
			Log.d(TAG, "mMovieInfo urls" + movieInfo.getBackdropImagesUrlsList());
		}
	}

	/* launch another async tast and download images from web */
	public void provideNextScreenForMovieDetails(final MovieDetails movieDetails) {
		Log.d(TAG, "GONNA GET SCREENS FOR MOVIE DETAILS");
		movieDetailsScreensRetrieverAsync = new MovieDetailsScreensRetrieverAsync();
		movieDetailsScreensRetrieverAsync.execute(movieDetails);
	}

	/* gets a movie list ordered by release, rating or title */
	public void manageMovieListForWidget(final String orderBy, final String results) {
		Log.d(TAG, "Going to get a movie list for WIDGET");
		/* get user settings */
		String language = context.getResources().getConfiguration().locale.getLanguage();
		String parserMode = settings.getParserMode();

		DownloadManager dManager = new DownloadManager();
		List<Movie> movies;
		try {
			movies = dManager.getMovieList(language, parserMode, orderBy, "1", results);
		} catch (GeneralException e) {
			Log.e(TAG, "TT", e);
			return;
		}

		if (orderBy.equals(MovieAppConstants.ORDER_BY_RELEASE)) {
			moviesByRelease = movies;
			Log.d(TAG, "in provideMovieListForWidget() setting mWidgetMoviesByRelease");
		} else if (orderBy.equals(MovieAppConstants.ORDER_BY_RATING)) {
			moviesByRating = movies;
			Log.d(TAG, "in provideMovieListForWidget() setting mWidgetMoviesByRating");
		} else {
			moviesByTitle = movies;
			Log.d(TAG, "in provideMovieListForWidget() setting mWidgetMoviesByTitle");
		}
	}

	public List<Movie> manageMovieForWidget(final String orderBy, final int position) {
		if (orderBy.equals(MovieAppConstants.ORDER_BY_RELEASE)) {
			return moviesByRelease;
		} else if (orderBy.equals(MovieAppConstants.ORDER_BY_RATING)) {
			return moviesByRating;
		} else {
			return moviesByTitle;
		}
	}

	public IMovieDetailsCallback getMovieInfoFragment() {
		return movieDetailsFragment;
	}

	public void setMovieInfoFragment(final IMovieDetailsCallback mMovieInfoFragment) {
		this.movieDetailsFragment = mMovieInfoFragment;
	}

	public boolean isConnected() {
		return isConnected;
	}

	public void setIsConnected(final boolean mIsConnected) {
		this.isConnected = mIsConnected;
	}

	public void cancelMovieDetailsFetching() {
		if (movieDetailsRetrieverAsync != null && movieDetailsRetrieverAsync.getStatus() == AsyncTask.Status.RUNNING) {
			Log.d(TAG, "canceling movieDetailsRetrieverAsync");
			movieDetailsRetrieverAsync.cancel(true);
		}
	}

	public void cancelScreensDownloading() {
		if (movieDetailsScreensRetrieverAsync != null
				&& movieDetailsScreensRetrieverAsync.getStatus() == AsyncTask.Status.RUNNING) {

			Log.d(TAG, "canceling mMovieInfoScreensRetrieverAsync");
			movieDetailsScreensRetrieverAsync.cancel(true);
		}
	}

	public Map<MovieListType, IMovieListFragmentCallback> getMovieListFragmentMap() {
		return movieListFragmentMap;
	}

	public void createMovieListFragmentMap() {
		movieListFragmentMap = new HashMap<MovieListType, IMovieListFragmentCallback>();
	}

	public List<Movie> getAppropriateMovieList(final String orderBy, final int page) {
		int start = DEFAULT_LIST_SIZE * (page - FIRST_PAGE);
		int end = DEFAULT_LIST_SIZE * page;
		if (orderBy.equals(MovieAppConstants.ORDER_BY_TITLE)) {
			if (moviesByTitle == null || moviesByTitle.size() < end) {
				return null;
			}
			return moviesByTitle.subList(start, end);
		} else if (orderBy.equals(MovieAppConstants.ORDER_BY_RELEASE)) {
			if (moviesByRelease == null || moviesByRelease.size() < end) {
				return null;
			}
			return moviesByRelease.subList(start, end);
		} else {
			if (moviesByRating == null || moviesByRating.size() < end) {
				return null;
			}
			return moviesByRating.subList(start, end);
		}
	}

	public List<Movie> getMovieList(final String orderBy) {
		if (orderBy.equals(MovieAppConstants.ORDER_BY_TITLE)) {
			return moviesByTitle;
		} else if (orderBy.equals(MovieAppConstants.ORDER_BY_RELEASE)) {
			return moviesByRelease;
		} else {
			return moviesByRating;
		}
	}

	public void addToMovieList(final List<Movie> movieListToSet, final String orderBy) {
		/* first time? - just set, not the 1st - add all */
		if (orderBy.equals(MovieAppConstants.ORDER_BY_TITLE)) {
			if (moviesByTitle == null) {
				moviesByTitle = movieListToSet;
				currentPageTitle = moviesByTitle.size() / DEFAULT_LIST_SIZE;
			} else {
				moviesByTitle.addAll(movieListToSet);
			}
		} else if (orderBy.equals(MovieAppConstants.ORDER_BY_RELEASE)) {
			if (moviesByRelease == null) {
				moviesByRelease = movieListToSet;
				currentPageRelease = moviesByRelease.size() / DEFAULT_LIST_SIZE;
			} else {
				moviesByRelease.addAll(movieListToSet);
			}
		} else if (orderBy.equals(MovieAppConstants.ORDER_BY_RATING)) {
			if (moviesByRating == null) {
				moviesByRating = movieListToSet;
				currentPageRating = moviesByRating.size() / DEFAULT_LIST_SIZE;
			} else {
				moviesByRating.addAll(movieListToSet);
			}
		} else {
			moviesSearchList = movieListToSet;
		}
	}

	private int getCurrentPage(final MovieListType listType) {
		switch (listType) {
			case TITLE:
				currentPageTitle++;
				return currentPageTitle;
			case RELEASE_DATE:
				currentPageRelease++;
				return currentPageRelease;
			case RATING:
				currentPageRating++;
				return currentPageRating;
			default:
				Log.d(TAG, "-=UNKNOWN=-");
				return 0;
		}
	}

	private String getSortingOrder(final MovieListType listType) {
		if (listType == MovieListType.TITLE) {
			return MovieAppConstants.ORDER_BY_TITLE;
		} else if (listType == MovieListType.RELEASE_DATE) {
			return MovieAppConstants.ORDER_BY_RELEASE;
		} else {
			return MovieAppConstants.ORDER_BY_RATING;
		}
	}

	/* builds movie list out of a cursor */
	private List<Movie> createMovieList(final Cursor cursor) {
		Log.d(TAG, "inside getMovieList() cursor.getCount() = " + cursor.getCount());

		if (cursor.moveToFirst()) {
			Log.d(TAG, "getting movies out of the cursor");
			List<Movie> movies = new ArrayList<Movie>();
			/* iterate over all cursor's rows and get column values into a movie object */
			do {
				Movie movie = new Movie();
				movie.setMovieId(cursor.getInt(cursor.getColumnIndex(MovieColumns.MOVIE_ID)));
				movie.setName(cursor.getString(cursor.getColumnIndex(MovieColumns.MOVIE_NAME)));
				movie.setCertification(cursor.getString(cursor.getColumnIndex(MovieColumns.MOVIE_CERTIFICATION)));
				movie.setVotes(cursor.getInt(cursor.getColumnIndex(MovieColumns.MOVIE_VOTES)));
				movie.setRating(cursor.getDouble(cursor.getColumnIndex(MovieColumns.MOVIE_RATING)));
				movie.setReleased(cursor.getString(cursor.getColumnIndex(MovieColumns.MOVIE_RELEASED)));
				movie.setUrl(cursor.getString(cursor.getColumnIndex(MovieColumns.MOVIE_URL)));
				movie.setThumbPosterUrl(cursor.getString(cursor.getColumnIndex(MovieColumns.MOVIE_POSTER_URL)));
				movies.add(movie);
			} while (cursor.moveToNext());
			cursor.close();
			return movies;
		}
		cursor.close();
		return null;
	}

	/* builds movie list out of a cursor */
	private void setMovieDetails(final MovieDetails movieInfo, final Cursor cursor) {
		Log.d(TAG, "inside setMovieDetails() cursor.getCount() = " + cursor.getCount());
		Log.d(TAG, "GETTING MOVIE INFO FROM cursor");
		if (cursor.moveToFirst()) {
			movieInfo.setMovieId(cursor.getInt(cursor.getColumnIndex(MovieColumns.MOVIE_ID)));
			movieInfo.setOverview(cursor.getString(cursor.getColumnIndex(MovieDetailsColumns.MOVIE_INFO_OVERVIEW)));
			movieInfo.setTrailerUrl(cursor.getString(cursor.getColumnIndex(MovieDetailsColumns.MOVIE_INFO_TRAILER)));
			movieInfo.setCastAsString(cursor.getString(cursor.getColumnIndex(MovieDetailsColumns.MOVIE_INFO_CAST)));

			cursor.close();
		}
		cursor.close();
	}

	private void setImageUrls(final MovieDetails movieInfo, final Cursor cursor) {
		Log.d(TAG, "inside setImageUrls() cursor.getCount() = " + cursor.getCount());
		Log.d(TAG, "GETTING MOVIE urls FROM cursor");
		movieInfo.setBackdropImagesUrls(new ArrayList<String>());
		movieInfo.setBackdropHDUrls(new ArrayList<String>());
		if (cursor.moveToFirst()) {
			do {
				String url = cursor.getString(cursor.getColumnIndex(MovieImageColumns.IMAGE_URL));
				if (cursor.getString(cursor.getColumnIndex(MovieImageColumns.IMAGE_SIZE)).equals("thumb")) {
					movieInfo.getBackdropImagesUrlsList().add(url);
				} else {
					movieInfo.getBackdropHDUrls().add(url);
				}
			} while (cursor.moveToNext());
		}
		cursor.close();
	}

	private synchronized MovieDetails getMovieScreen(final MovieDetails movieDetails) {
		List<String> backdropUrls = movieDetails.getBackdropImagesUrlsList();

		/* load screens from web and store them on a device */
		int backdropPosition = backdropUrls.size() - movieDetails.getBackdropBitmaps().size();
		Log.d(TAG, "backdrop urls = " + backdropUrls.size() + " backdrop bitmaps = "
				+ movieDetails.getBackdropBitmaps().size());
		if (backdropPosition > 0) {
			String url = backdropUrls.get(backdropPosition - 1);
			movieDetails.getBackdropBitmaps().add(bitMapManager.fetchBitmap(url));
		}
		return movieDetails;
	}

	/* first asynchronous task that retrieves a movie list in a background thread */
	private class MovieListRetrieverAsync extends AsyncTask<ListTypeWrapper, Void, List<Movie>> {

		private final String TAG = MovieListRetrieverAsync.class.getSimpleName();
		private MovieListType fragmentType;
		private int page;

		@Override
		protected List<Movie> doInBackground(final ListTypeWrapper... params) {
			/* get user settings */
			String language = context.getResources().getConfiguration().locale.getLanguage();
			fragmentType = params[0].getListType();
			page = params[0].getCurrentPage();
			String parserMode = settings.getParserMode();
			String orderBy = getSortingOrder(fragmentType);

			String results = String.valueOf(DEFAULT_LIST_SIZE);
			Log.e(TAG, "LOCALE IS = " + language + " & parser mode " + parserMode + " & fragmentType " + fragmentType
					+ " & orderBy " + orderBy + " & page " + page);

			/* get a list of movies */
			/* Cursor cursor = mContext.getContentResolver().query(ContentUris.withAppendedId
			 * (MovieListProvider.CONTENT_URI, 2), null, null, new String[] { results, language, parserMode }, " DESC"); */

			Cursor cursor = context.getContentResolver().query(MovieListProvider.CONTENT_URI, null, null,
					new String[] { language, parserMode, String.valueOf(page), results, orderBy }, " DESC");
			Log.d(TAG, "GOT cursor");
			if (cursor == null) {
				Log.d(TAG, "cursor == null");
				return null;
			} else {
				Log.d(TAG, "cursor != null");
				Log.d(TAG, "cursor.getColumnCount() = " + cursor.getColumnCount());
			}
			List<Movie> movies = createMovieList(cursor);
			addToMovieList(movies, orderBy);
			return movies;
		}

		/* receives ArrayList<Movie> from doInBackground() */
		@Override
		protected void onPostExecute(final List<Movie> result) {
			if (result != null) {
				if (page == FIRST_PAGE) {
					Log.d(TAG, "onPostExecute fragmentType " + fragmentType + " calling onMovieListRetrieved(result)");
					movieListFragmentMap.get(fragmentType).onMovieListRetrieved(result);
				} else {
					movieListFragmentMap.get(fragmentType).onMovieListUpdated(result);
					Log.d(TAG, "onPostExecute fragmentType " + fragmentType + " calling onMovieListUpdated(result)");
				}
			} else {
				Log.d(TAG, "onPostExecute fragmentType " + fragmentType + " result == null");
				movieListFragmentMap.get(fragmentType).onMovieListRetrievalFailed();
			}
		}
	}

	/* second asynchronous task that retrieves a movie information in a background thread */
	private class MovieDetailsRetrieverAsync extends AsyncTask<Integer, Void, MovieDetails> {

		private final String TAG = MovieDetailsRetrieverAsync.class.getSimpleName();

		@Override
		protected void onPreExecute() {
			movieDetailsFragment.onGettingMovieInfo();
		}

		@Override
		protected MovieDetails doInBackground(final Integer... params) {
			/* get user settings */
			String language = context.getResources().getConfiguration().locale.getLanguage();
			String parserMode = settings.getParserMode();

			int movieId = params[0];
			Log.d(TAG, "inside doInBackground(final Integer... params)\n and movieId = " + movieId);
			/* get a list of movies */
			Cursor movieInfoCursor = context.getContentResolver().query(
					ContentUris.withAppendedId(MovieDetailsProvider.CONTENT_URI, movieId), null, null,
					new String[] { language, parserMode }, "");
			if (movieInfoCursor == null) {
				return null;
			}
			movieInfo = new MovieDetails();
			setMovieDetails(movieInfo, movieInfoCursor);

			movieInfoCursor = context.getContentResolver().query(
					Uri.parse(MovieDetailsProvider.CONTENT_URI + "/backdrops/" + movieId), null, null, null, null);
			setImageUrls(movieInfo, movieInfoCursor);
			return movieInfo;
		}

		@Override
		protected void onPostExecute(final MovieDetails result) {
			if (result == null) {
				movieDetailsFragment.onMovieInfoRetrievalFailed();
			} else {
				movieDetailsFragment.onMovieInfoRetrieved(result);
			}
		}
	}

	/* third asynchronous task that searches for a movie title in a background thread */
	private class SearchMovieListAsync extends AsyncTask<String, Void, List<Movie>> {

		private final String TAG = SearchMovieListAsync.class.getSimpleName();

		@Override
		protected List<Movie> doInBackground(final String... params) {
			/* get user settings */
			lastSearchQuery = params[0];
			String language = context.getResources().getConfiguration().locale.getLanguage();
			String parserMode = settings.getParserMode();
			Log.d(TAG, "inside doInBackground(final String... params)\n and Search query IS " + lastSearchQuery);

			Cursor cursor = context.getContentResolver().query(
					Uri.parse(MovieListProvider.CONTENT_URI + "/search/" + lastSearchQuery), null, null,
					new String[] { language, parserMode }, " DESC");
			Log.d(TAG, "GOT cursor");
			if (cursor == null) {
				Log.d(TAG, "cursor == null");
				return null;
			} else {
				Log.d(TAG, "cursor != null");
				Log.d(TAG, "cursor.getColumnCount() = " + cursor.getColumnCount());
			}
			moviesSearchList = createMovieList(cursor);
			return moviesSearchList;
		}

		/* receives ArrayList<Movie> from doInBackground() */
		@Override
		protected void onPostExecute(final List<Movie> result) {
			if (result == null) {
				movieListFragmentMap.get(MovieListType.SEARCH).onMovieListRetrievalFailed();
			} else {
				movieListFragmentMap.get(MovieListType.SEARCH).onMovieListRetrieved(result);
			}
		}
	}

	/* fifth asynchronous task that retrieves a movie screens in a background thread */
	private class MovieDetailsScreensRetrieverAsync extends AsyncTask<MovieDetails, Void, MovieDetails> {

		private final String TAG = MovieDetailsScreensRetrieverAsync.class.getSimpleName();

		@Override
		protected MovieDetails doInBackground(final MovieDetails... paramArrayOfParams) {
			return getMovieScreen(paramArrayOfParams[0]);
		}

		@Override
		protected void onPostExecute(final MovieDetails result) {
			Log.d(TAG, "onPostExecute(final MovieDetails result)");
			if (result == null) {
				movieDetailsFragment.onMovieInfoRetrievalFailed();
			} else {
				movieDetailsFragment.onMovieInfoRetrieved(result);
			}
		}
	}

	private class MoviePosterRetrieverAsync extends AsyncTask<ListWrapper, Void, Void> {

		// private final String TAG =
		// MoviePosterRetrieverAsync.class.getSimpleName();
		private MovieListType fragmentType;

		@Override
		protected Void doInBackground(final ListWrapper... arrayOfUrls) {
			List<Movie> movies = arrayOfUrls[0].getMovies();
			fragmentType = arrayOfUrls[0].getFragmentType();
			int listSize = movies.size();
			for (Movie movie : movies) {
				Bitmap bitmap = bitMapManager.fetchBitmap(movie.getThumbPosterUrl());
				if (bitmap != null) {
					movie.setPosterBitmap(bitmap);
					movie.setPosterRecycled(false);
					if (listSize % 2 != 0) {
						publishProgress();
					}
				}
				listSize--;
			}
			return null;
		}

		@Override
		protected void onProgressUpdate(final Void... values) {
			movieListFragmentMap.get(fragmentType).onMoviePosterRetreived();
		}
	}

	private class ListWrapper {

		private List<Movie> movies;
		private MovieListType fragmentType;

		public List<Movie> getMovies() {
			return movies;
		}

		public void setMovies(final List<Movie> movies) {
			this.movies = movies;
		}

		public MovieListType getFragmentType() {
			return fragmentType;
		}

		public void setFragmentType(final MovieListType fragmentType) {
			this.fragmentType = fragmentType;
		}
	}

	private class ListTypeWrapper {

		private MovieListType listType;
		private int currentPage;

		public MovieListType getListType() {
			return listType;
		}

		public void setListType(final MovieListType listType) {
			this.listType = listType;
		}

		public int getCurrentPage() {
			return currentPage;
		}

		public void setCurrentPage(final int currentPage) {
			this.currentPage = currentPage;
		}
	}

	@SuppressWarnings("rawtypes")
	public class AsyncTaskWrapper {

		private AsyncTask task;

		public AsyncTaskWrapper(final AsyncTask task) {
			this.task = task;
		}

		public void cancel() {
			task.cancel(true);
		}
	}
}
